﻿// ActionScript file
//--------------------------------------------------------------
//
// Qizhi Zhang 
// ezhung@gmail.com
// http://www.moorwind.com
//
//--------------------------------------------------------------
package com.moorwind.ai.math
{
    /** 向量  */
    public class Vector
    {
        //////////////////////////////////////////////////////////////////////////////
        //Public properties
        
        public var x:Number;
        public var y:Number;
        public var z:Number;        
        
        /**
         * 向量的模
         */
        public function get length():Number
        {
            return Math.sqrt(x*x + y*y + z*z);
        }
        
        /**
         * 共轭向量
         */
        public function get conjugationVector():Vector
        {
            return new Vector(-x, -y, -z);
        }
        
        //////////////////////////////////////////////////////////////////////////////
        //Constructor
        
        /** 构造函�? */
        public function Vector(x:Number = 0, y:Number = 0, z:Number = 0)
        {
            this.x = x;
            this.y = y;
            this.z = z;
        }        
        
        //////////////////////////////////////////////////////////////////////////////
        //methods
        
        /**
         * 向量+=
         */
        public function add(v:Vector):void
        {
            x += v.x;
            y += v.y;
            z += v.z;
        }
        /**
         * 向量加法
         */
        public static function addition(u:Vector, v:Vector):Vector
        {
            return new Vector(u.x + v.x, u.y + v.y, u.z + v.z);
        }
        
        /**
         * 向量-=
         */
        public function sub(v:Vector):void
        {
            x -= v.x;
            y -= v.y;
            z -= v.z;
        }
        /**
         * 向量减法
         */
        public function subtraction(u:Vector, v:Vector):Vector
        {
            return new Vector(u.x - v.x, u.y - v.y, u.z - v.z);
        }
        
        /**
         * 向量*=
         */
        public function mul(v:Vector):void
        {
            x *= v.x;
            y *= v.y;
            z *= v.z;
        }
        
        /**
         * 向量与数量的乘法
         */
        public static function multiplication(s:Number, v:Vector):Vector
        {
            return new Vector(s*v.x, s*v.y, s*v.z);
        }
        
        
        /**
         * 向量的外积（叉积�?
         */
        public static function exterior(u:Vector, v:Vector):Vector
        {
            return new Vector( u.y * v.z - u.z * v.y,
                                u.z * v.x - u.x * v.z,
                                u.x * v.y - u.y * v.x);
        }
        
        /**
         * 向量的内�?
         */
        public static function interior(u:Vector, v:Vector):Number
        {
            return u.x * v.x + u.y * v.y + u.z * v.z;
        }
        
        /**
         * 向量的混合积
         */
        public static function tripleScalarProduct(u:Vector, v:Vector, w:Vector):Number
        {
            return (u.x * (v.y * w.z - v.z * w.y)) +
                    (u.y * (-v.x * w.z + v.z * w.x)) +
                    (u.z * (v.x * w.y - v.y * w.z));
        }
        
        /**
         * 向量除法 /=
         */
        public function div(v:Vector):void
        {
            x /= v.x;
            y /= v.y;
            z /= v.z;
        }
        
        /**
         * 向量与数量的除法
         */
        public static function division(v:Vector, s:Number):Vector
        {
            return new Vector(v.x/s, v.y/s, v.z/s);
        }
                
        /**
         * 标准化本向量(将本向量转化为单位向�?
         */
        public function normalize():void
        {
            var m:Number = Math.sqrt(x*x + y*y + z*z);
            if(m < MathConst.TOL) m = 1;
            x /= m;
            y /= m;
            z /= m;
            
            if(Math.abs(x) < MathConst.TOL) x = 0.0;
            if(Math.abs(y) < MathConst.TOL) y = 0.0;
            if(Math.abs(z) < MathConst.TOL) z = 0.0;
        }
                
        /**
         * 反向量本向量
         */
        public function reverse():void
        {
            x = -x;
            y = -y;
            z = -z;
        }

    }
}